#ifndef STATEMAN_H
#define STATEMAN_H

#include <stack>

#include <OIS.h>
#include <time.h>

#include <assert.h>
#include "State.h"


namespace pong {
	/// A manager for game states. More or less a light stack wrapper
    class StateManager {
    protected:
        Core* core; // The core this state manager is bound to
        std::stack<State*> states;

    public:
        StateManager(Core* const c)
            : core(c)
        {
			assert(c && "Cannot initialize with null core!");
		}
        ~StateManager(void);

        inline State* currentState(void) const {return states.top();}

		// Pushes the given state to the stack after loading it
        inline void push(State* s) {
			assert (s && "Pushing a null state is bad!");
            s->load(*core);
            states.push(s);
        }
		// Pops the given state from the stack and then calls its unload
        inline void pop(void) {
			State* const popped = currentState();
            states.pop();
            popped->unload(*core);
        }

        inline bool processKeyPress(const OIS::KeyEvent& e) const {
            return currentState()->keyPressed(e);
        }
        inline bool processKeyRelease(const OIS::KeyEvent& e) const {
            return currentState()->keyReleased(e);
        }

        inline bool processMouseMove(const OIS::MouseEvent& e) const {
            return currentState()->mouseMoved(e);
        }
        inline bool processMousePress(const OIS::MouseEvent& e, OIS::MouseButtonID btn) const {
            return currentState()->mousePressed(e, btn);
        }
        inline bool processMouseRelease(const OIS::MouseEvent& e, OIS::MouseButtonID btn) const {
            return currentState()->mouseReleased(e, btn);
        }

		inline bool update() {
			return currentState()->update(*core);
		}
    };
}
#endif //STATEMAN_H